//== SAGITTARIUS ============================================================================

//== BEGINNING OF CODE ===============================================================

#include "sagittarius/core/SagittariusCore.h"

//SAGITTARIUS headers:
#include "sagittarius/lexer/lParser.h"
#include "sagittarius/io/io.h"

//#include <stdio.h>
//#include <time.h>
//#include <malloc.h>
#include <string.h>
#include <math.h>

// #define PRINT_EXPANSIONS

#ifdef PRINT_EXPANSIONS
    #include "sagittarius/io/io.h"
    #define USING_EXPANSION(x) SG_WRITE(1, x); LX_WRITE_BUF(1, state->w); SG_WRITE(1, "\n");
#else
    #define USING_EXPANSION(x)
#endif

int lmatch(lparserState* state, LXFixedType c) {
    //AT(!LX_CMPALPHA_EQ_SPC(*state->w, UC_Null));
    //AT(LX_CMPALPHA_EQ_SPC(*state->w, c));
    if(LX_CMPALPHA_EQ_SPC(*state->w, c)) {
        ++state->w;
        return 1;
    } else {
        return 0;
    }
}

//tries to match the whole string, resets position if it can't
int l_trymatchstr(lparserState* state, const char* str) {
    constLexBuf sstart = state->w;
    while(*str != '\0') {
        if(!LX_CMPALPHA_EQ_SPC(*state->w, *str)) {
            state->w = sstart;
            return 0;
        }
        ++state->w;
        ++str;
    }
    return 1;
}

void lconsume(lparserState* state, LXAlphaType* r) {
    AT(!LX_CMPALPHA_EQ_SPC(*state->w, UC_Null), "Consumed end of buffer");
    if(r)
        LX_ALPHA_SET(*r, *state->w);
    ++state->w;
}

int lisControlTok(LXFixedType x) {
    switch (x) {
        case CONST_RECH_BLANK:
            return 1;
            break;
        case CONST_RECH_TAB:
            return 1;
            break;
        case CONST_RECH_LF:
            return 1;
            break;
        case CONST_RECH_CR:
            return 1;
            break;
        case CONST_RECH_AMP:
            return 1;
            break;
        case CONST_RECH_LPAREN:
            return 1;
            break;
        case CONST_RECH_RPAREN:
            return 1;
            break;
        case CONST_RECH_STAR:
            return 1;
            break;
        case CONST_RECH_CARROT:
            return 1;
            break;
        case CONST_RECH_VBAR:
            return 1;
            break;
        case CONST_RECH_LBRAK:
            return 1;
            break;
        case CONST_RECH_RBRAK:
            return 1;
            break;
        /*case CONST_RECH_BSLASH:
            return 1;
            break;*/
        //only in sets
        /*case CONST_RECH_DASH:
            return 1;
            break;*/
        case CONST_RECH_PLUS:
            return 1;
            break;
        case CONST_RECH_QUES:
            return 1;
            break;
        case CONST_RECH_EQ:
            return 1;
            break;
        case CONST_RECH_NULL:
            return 1;
            break;
        default:
            return 0;
    }
}

lparserState lex_createParserState(constLexBuf w) {
    lparserState r;
    r.w = w;
    AT(!LX_IS_NULL(*r.w), "Begins with null char");
    return r;
}

/// lex_parseWS
void lex_parseWS(lparserState* state, lparserInfo* pi) {
    int miss=0;
    while(LX_CMPALPHA_EQ_SPC(*state->w, CONST_RECH_BLANK) || LX_CMPALPHA_EQ_SPC(*state->w, CONST_RECH_TAB) || LX_CMPALPHA_EQ_SPC(*state->w, CONST_RECH_LF) || LX_CMPALPHA_EQ_SPC(*state->w, CONST_RECH_CR)
        || LX_CMPALPHA_EQ_SPC(*state->w, CONST_RECH_BSLASH)) {
        if(LX_CMPALPHA_EQ_SPC(*state->w, CONST_RECH_NULLCHR))
            return; //end of string
        if(LX_CMPALPHA_EQ_SPC(*state->w, CONST_RECH_BSLASH)) {
            //line continuation
            ++state->w;
            while(LX_CMPALPHA_EQ_SPC(*state->w, CONST_RECH_LF) || LX_CMPALPHA_EQ_SPC(*state->w, CONST_RECH_CR)) {
                ++state->w;
                miss = 1;
            }
            if(!miss) {
                //backslash was not followed by a line break
                --state->w;
                break;
            }
        }
        ++state->w;
    }
}

//Does not eat newlines etc.
void lex_parseSpace(lparserState* state, lparserInfo* pi) {
    int miss=0;
    while(LX_CMPALPHA_EQ_SPC(*state->w, CONST_RECH_BLANK) || LX_CMPALPHA_EQ_SPC(*state->w, CONST_RECH_TAB)
        || LX_CMPALPHA_EQ_SPC(*state->w, CONST_RECH_BSLASH)) {
        if(LX_CMPALPHA_EQ_SPC(*state->w, CONST_RECH_BSLASH)) {
            //line continuation
            ++state->w;
            while(LX_CMPALPHA_EQ_SPC(*state->w, CONST_RECH_LF) || LX_CMPALPHA_EQ_SPC(*state->w, CONST_RECH_CR)) {
                ++state->w;
                miss = 1;
            }
            if(!miss) {
                //backslash was not followed by a line break
                --state->w;
                break;
            }
        }
        ++state->w;
    }
}

/// lex_parseVars
void lex_parseVars(lparserState* state, lparserInfo* pi) {
    while(!l_trymatchstr(state, "end")) {
        lex_parseVar(state, pi);
    }
}

/// lex_parseVar
lexvar lex_parseVar(lparserState* state, lparserInfo* pi) {
    lexvar v;
    //puts result in a pool buffer - okay?
    //it should be, since this is used to parse all identifiers
    v.name = lex_parseID(state, pi);
    AN(v.name, "Malformed var id");
    lex_parseWS(state, pi);
    if(lmatch(state, '=')) {
        lex_parseWS(state, pi);
        v.haveintv = 1;
        v.initval = lex_parseUInt(state, pi);
    } else {
        AN(0);
    }
    return v;
}

/// lex_parseAssn
lexvece* lex_parseAssn(lparserState* state, lparserInfo* pi) {
    constLexBuf startw = state->w;
    lexvece* e;
    lASTNode *r;
    LexBuf id, exp;
    
    USING_EXPANSION("Assn -> id = E\n");
    id = lex_parseID(state, pi);
    lex_parseWS(state, pi);
    if(!lmatch(state, '=')) {
        USING_EXPANSION("Backtrack on Assn\n");
        if(id)
            LX_FREE_BUFFER(id);
        state->w = startw;
        return NULL;
    } else
        ++state->w;
    
    lex_parseWS(state, pi);
    exp = lex_parseExpStr(state, pi);
    r = lex_parseExpE(state, pi);
    
    e = create_lexvece();
    e->id = id;
    e->ownid = 1;
    e->exp = exp;
    e->ownexp = 1;
    e->r = r;
    
    //see if there are any actions associated with this pattern
    lex_parseSpace(state, pi);
    startw = state->w;
    if(lmatch(state, '-') && lmatch(state, '>')) {
        //allocate action chain
        e->act = lex_createActChain();
        e->ownact = 1;
        do {
            lexaction a;
            a.id = NULL;
            //found actions
            lex_parseSpace(state, pi);
            if(l_trymatchstr(state, "stop")) {
                //try "stop"
                a.type = LEX_ACTION_STOP;
            } else if(l_trymatchstr(state, "reset")) {
                //try "reset"
                a.type = LEX_ACTION_RESET;
            } else {
                LexBuf id = lex_parseID(state, pi);
                if(l_trymatchstr(state, "++")) {
                    a.type = LEX_VAR_INC;
                    a.id = id;
                } else {
                    AN(0, "Unknown action type");
                }
            }
            lex_pushAct(e->act, a);
            lex_parseSpace(state, pi);
        } while(lmatch(state, ','));
    } else {
        state->w = startw;
    }
    
    if(lmatch(state, '#')) {
        lex_parseComment(state, pi);
    }
    
    return e;
}

LexBuf lex_parseID(lparserState* state, lparserInfo* pi) {
    //lASTNode* r;
    LexBuf id;
    size_t len;
    constLexBuf wstart = state->w;
    while(!lisControlTok(LX_GET_FIXED_VALUE(*state->w))) {
        ++state->w;
    }
    if(state->w == wstart)
        return NULL;
    len = (intptr_t)(state->w - wstart)+1;
    /*r = lAST_createNode();
    r->type = AST_NODE_TYPE_ID;
    
    r->p = LX_CREATE_POOL_BUF(len);
    LX_COPY(r->p, wstart, len-1);
    LX_ALPHA_SET_SPC(((LexBuf)r->p)[len-1], '\0');*/
    
    id = LX_CREATE_POOL_BUF(len);
    LX_COPY(id, wstart, len-1);
    LX_ALPHA_SET_SPC(id[len-1], '\0');
    
    return id;
}

uint64 lex_getDigitVal(LXAlphaType x) {
    switch(LX_GET_FIXED_VALUE(x)) {
        case '0':
            return 0;
        case '1':
            return 1;
        case '2':
            return 2;
        case '3':
            return 3;
        case '4':
            return 4;
        case '5':
            return 5;
        case '6':
            return 6;
        case '7':
            return 7;
        case '8':
            return 8;
        case '9':
            return 9;
        default:
            return -1;
    }
}

uint64 lex_parseUInt(lparserState* state, lparserInfo* pi) {
    //lASTNode* r;
    size_t pr=0;
    //constLexBuf wstart = state->w;
    uint64 r=0, d;
    while(1) {
        d = lex_getDigitVal(*state->w);
        if(d == -1)
            break;
        r += d*pow(10, pr);
        AT(d != -1, "Shouldn't happen");
        
        ++state->w;
        ++pr;
    }
    if(pr == 0) {
        AN(0, "lex_parseUInt: Invalid input (not an unsigned int)");
        return -1; //error (wraps to max val for uint64)
    }
    
    return r;
}

LexBuf lex_parseExpStr(lparserState* state, lparserInfo* pi) {
    LexBuf exp;
    size_t len;
    int level=0;
    constLexBuf wstart = state->w;
    while(!LX_CMPALPHA_EQ_SPC(*state->w, 0)) {
        if(level == 0 && LX_CMPALPHA_EQ_SPC(*state->w, CONST_RECH_SPACE))
            break;
        if(LX_CMPALPHA_EQ_SPC(*state->w, CONST_RECH_BSLASH)) {
            //escape sequence
            ++state->w;
            if(LX_CMPALPHA_EQ_SPC(*state->w, 0))
                return NULL;
            ++state->w;
        }
        if(level < 0)
            return NULL;
        if(LX_CMPALPHA_EQ_SPC(*state->w, CONST_RECH_LPAREN))
            ++level;
        if(LX_CMPALPHA_EQ_SPC(*state->w, CONST_RECH_RPAREN))
            --level;
        ++state->w;
    }
    if(state->w == wstart)
        return NULL;
    len = (intptr_t)(state->w - wstart)+1;
    
    exp = LX_CREATE_POOL_BUF(len);
    LX_COPY(exp, wstart, len-1);
    LX_ALPHA_SET_SPC(exp[len-1], '\0');
    
    state->w = wstart;
    
    return exp;
}

lASTNode* lex_parseExpE(lparserState* state, lparserInfo* pi) {
    //E must expand E -> |TE'
    USING_EXPANSION("E -> OE'\n");
	{
		lASTNode* o = lex_parseExpO(state, pi);
		lASTNode* ep = lex_parseExpEp(state, pi);
		if(ep) {
			lASTNode* int_node = lAST_createNode();
			int_node->type = AST_NODE_TYPE_REINTERSECTION;
			int_node->n1 = o;
			int_node->n2 = ep;
			#ifdef LEXPARSER_COMPUTE_NULLABLE
				int_node->nullable = int_node->n1->nullable && int_node->n2->nullable;
			#endif
			return int_node;
		} else {
			return o;
		}
	}
}

lASTNode* lex_parseExpEp(lparserState* state, lparserInfo* pi) {
    if(LX_CMPALPHA_EQ_SPC(*state->w, CONST_RECH_AMP)) {
        lconsume(state, NULL);
        //use expansion E'-> |TE'
        USING_EXPANSION("E' -> &OE'\n");
		{
			lASTNode* o = lex_parseExpO(state, pi);
			lASTNode* ep = lex_parseExpEp(state, pi);
			if(ep) {
				lASTNode* int_node = lAST_createNode();
				int_node->type = AST_NODE_TYPE_REINTERSECTION;
				int_node->n1 = o;
				int_node->n2 = ep;
				#ifdef LEXPARSER_COMPUTE_NULLABLE
					int_node->nullable = int_node->n1->nullable && int_node->n2->nullable;
				#endif
				return int_node;
			} else {
				return o;
			}
		}
    } else {
        //use expansion E' -> ep
        return NULL;
    }
}

lASTNode* lex_parseExpO(lparserState* state, lparserInfo* pi) {
    //O must expand: O -> TO'
    USING_EXPANSION("O -> TO'\n");
	{
		lASTNode* t = lex_parseExpT(state, pi);
		lASTNode* op = lex_parseExpOp(state, pi);
		if(op) {
			lASTNode* union_node = lAST_createNode();
			union_node->type = AST_NODE_TYPE_REUNION;
			union_node->n1 = t;
			union_node->n2 = op;
			#ifdef LEXPARSER_COMPUTE_NULLABLE
				union_node->nullable = union_node->n1->nullable || union_node->n2->nullable;
			#endif
			return union_node;
		} else {
			return t;
		}
	}
}

lASTNode* lex_parseExpOp(lparserState* state, lparserInfo* pi) {
    if(LX_CMPALPHA_EQ_SPC(*state->w, CONST_RECH_VBAR)) {
        lconsume(state, NULL);
        //use expansion E'->|TE'
        USING_EXPANSION("E' -> |TE'\n");
		{
			lASTNode* t = lex_parseExpT(state, pi);
			lASTNode* op = lex_parseExpOp(state, pi);
			if(op) {
				lASTNode* union_node = lAST_createNode();
				union_node->type = AST_NODE_TYPE_REUNION;
				union_node->n1 = t;
				union_node->n2 = op;
				#ifdef LEXPARSER_COMPUTE_NULLABLE
					union_node->nullable = union_node->n1->nullable || union_node->n2->nullable;
				#endif
				return union_node;
			} else {
				return t;
			}
		}
    } else {
        //use expansion E' -> ep
        return NULL;
    }
}

lASTNode* lex_parseExpT(lparserState* state, lparserInfo* pi) {
    //T must expand: T -> FT'
    USING_EXPANSION("T -> FT'\n");
	{
		lASTNode* f = lex_parseExpF(state, pi);
		lASTNode* tp = lex_parseExpTp(state, pi);
		if(tp) {
			lASTNode* concat_node = lAST_createNode();
			concat_node->type = AST_NODE_TYPE_RECONCAT;
			concat_node->n1 = f;
			concat_node->n2 = tp;
			#ifdef LEXPARSER_COMPUTE_NULLABLE
				concat_node->nullable = concat_node->n1->nullable && concat_node->n2->nullable;
			#endif
			return concat_node;
		} else {
			return f;
		}
	}
}

lASTNode* lex_parseExpTp(lparserState* state, lparserInfo* pi) {
    //determine if char is in FIRST(T')
    if(!lisControlTok(LX_GET_FIXED_VALUE(*state->w)) || LX_CMPALPHA_EQ_SPC(*state->w, CONST_RECH_LPAREN) || LX_CMPALPHA_EQ_SPC(*state->w, CONST_RECH_LBRAK) ||
         LX_CMPALPHA_EQ_SPC(*state->w, CONST_RECH_CARROT)
    ) {
        //expand T' -> FT'
        USING_EXPANSION("T' -> FT'\n");
		{
			lASTNode* f = lex_parseExpF(state, pi);
			lASTNode* tp = lex_parseExpTp(state, pi);
			if(tp) {
				lASTNode* concat_node = lAST_createNode();
				concat_node->type = AST_NODE_TYPE_RECONCAT;
				concat_node->n1 = f;
				concat_node->n2 = tp;
				#ifdef LEXPARSER_COMPUTE_NULLABLE
					concat_node->nullable = concat_node->n1->nullable && concat_node->n2->nullable;
				#endif
				return concat_node;
			} else {
				return f;
			}
		}
    } else {
        //expand T' -> ep
        return NULL; //empty
    }
}

lASTNode* lex_parseExpF(lparserState* state, lparserInfo* pi) {
    lASTNode* e;
    //match negation, if available
    int do_inv = 0;
    if(LX_CMPALPHA_EQ_SPC(*state->w, CONST_RECH_CARROT)) {
        do_inv = 1;
        lconsume(state, NULL); //'^'
    }
    
    if(LX_CMPALPHA_EQ_SPC(*state->w, CONST_RECH_LPAREN)) {
        //use expansion F -> (E)
        USING_EXPANSION("F -> (E)\n");
        lconsume(state, NULL); //'('
        e = lex_parseExpE(state, pi);
        if(!lmatch(state, CONST_RECH_RPAREN))
            return NULL;
        #ifndef DISTRIBUTE_COMPLEMENT
            //AN(distributeComplement(e));
        #endif
    } else {
        if(LX_CMPALPHA_EQ_SPC(*state->w, UC_Null)) {
            SAGITTARIUS_ASSERT(0 && "Reached end of buffer expecting primitive");
            return 0;
        }
        //use expansion F -> sym
        USING_EXPANSION("F -> sym\n");
        e = lex_parseExpPrimitive(state, pi);
    }
    e->inv = do_inv; //apply negation if appropriate
    #ifdef LEXPARSER_COMPUTE_NULLABLE
        if(e->inv) e->nullable = !e->nullable;
    #endif
    //match closure, if available
    if(lmatch(state, CONST_RECH_STAR)) {
        e->closed = 1;
        #ifdef LEXPARSER_COMPUTE_NULLABLE
            e->nullable = 1;
        #endif
        return e;
    }
    //match + operator
    if(lmatch(state, CONST_RECH_PLUS)) {
        lASTNode *f,*g;
        #if LX_USE_POOLALLOC
        //just so we can set it as closed
        f = lAST_shallowCopy(e);
        #else
        f = e;
        #endif
        #ifdef LEXPARSER_COMPUTE_NULLABLE
            f->nullable = 1;
        #endif
        g = lex_constructNodeConcat(e,f);
        lAST_destroy_node(e);
        g->n2->closed = 1;
        #ifdef LEXPARSER_COMPUTE_NULLABLE
            g->n2->nullable = 1;
        #endif
        SG_WRITE(2, "Fresh:\n");
        lex_writeOut(2, g, 0);
        return g;
    }
    //match ? operator
    if(lmatch(state, CONST_RECH_QUES)) {
        lASTNode *f,*g;
        f = lex_constructEmptyStr(e);
        g = lex_constructNodeUnion(e,f);
        lAST_destroy_node(e);
        lAST_destroy_node(f);
        return g;
    }
    return e;
}

/// lex_parseExpPrimitive
lASTNode* lex_parseExpPrimitive(lparserState* state, lparserInfo* pi) {
    int neg=0;
    lASTNode* n = lAST_createNode();
    LXAlphaType c, d;
    RE_CharSet *cs, *csunion;
    SAGITTARIUS_ASSERT(n);
    n->type = AST_NODE_TYPE_REPRIMITIVE;
    
    LX_FORCE_INIT(c);
    LX_FORCE_INIT(d);
    lconsume(state, &c);
    
    if(LX_CMPALPHA_EQ_SPC(c, CONST_RECH_LBRAK)) {
        //get next character
        lconsume(state, &c);
        //carrot
        if(LX_CMPALPHA_EQ_SPC(c, CONST_RECH_CARROT)) {
            neg = 1;
            lconsume(state, &c);
        }
        //character class
        while(!LX_CMPALPHA_EQ_SPC(c, CONST_RECH_RBRAK)) {
            //end-of-input
            if(LX_CMPALPHA_EQ_SPC(c, UC_Null)) {
                lAST_destroy_node(n);
                AN(0, "Expected ]");
                return NULL;
            } else if(LX_CMPALPHA_EQ_SPC(c, CONST_RECH_CARROT)) {
                //carrot
                lAST_destroy_node(n);
                AN(0, "Unexpected ^ in char class");
                return NULL;
            } else if(LX_CMPALPHA_EQ_SPC(c, CONST_RECH_BSLASH)) {
                //backslash: escaped char
                lex_parseSetEscapedSymbol(state, pi, &c);
            }
            
            if(lmatch(state, CONST_RECH_DASH)) {
                //range
                lconsume(state, &d);
                //backslash: escaped char
                if(LX_CMPALPHA_EQ_SPC(c, CONST_RECH_BSLASH)) {
                    lex_parseSetEscapedSymbol(state, pi, &d);
                }
                AT(!lisControlTok(LX_GET_FIXED_VALUE(d)), "Found stray control token in range");
                cs = re_createCSRange(c, d);
            } else {
                //single char
                cs = re_createCSSym(c);
            }
            
            if(n->cs) {
                csunion = re_CSUnion(n->cs, cs);
                re_destroyCS(cs);
                re_destroyCS(n->cs);
                n->cs = csunion;
            } else {
                n->cs = cs;
            }
            
            lconsume(state, &c);
        }
    } else {
        AT(!lisControlTok(LX_GET_FIXED_VALUE(c)), "Found stray control token"); //used to pass c && "Found stray control token" to isControlTok - DANGEROUS!
        //backslash: escaped char
        if(LX_CMPALPHA_EQ_SPC(c, CONST_RECH_BSLASH)) {
            lex_parseEscapedSymbol(state, pi, &c);
        }
        if(LX_CMPALPHA_EQ(c, pi->emptychr)) {
            n->cs = re_createCSEmptyStr();
            #ifdef LEXPARSER_COMPUTE_NULLABLE
                n->nullable = 1;
            #endif
        } else
            n->cs = re_createCSSym(c);
    }
    
    if(n->cs) {
        //must be sorted for re_CSComplement and others
        re_CSSortInPlace(n->cs);
        if(neg) {
            cs = re_CSComplement(n->cs);
            re_destroyCS(n->cs);
            n->cs = cs;
        }
    }
    
    LX_ALPHA_CLEAR(c);
    LX_ALPHA_CLEAR(d);
    
    return n;
}

/// lex_parseEscapedSymbol
inline void lex_parseEscapedSymbol(lparserState* state, lparserInfo* pi, LXAlphaType* c) {
    lconsume(state, c);
    switch(LX_GET_FIXED_VALUE(*c)) {
        case CONST_RECH_BSLASH:
            //a real backslash
            break;
        case '0':
            //null char
            LX_ALPHA_SET_SPC(*c, CONST_RECH_NULLCHR);
            break;
        case CONST_RECH_LPAREN:
            //'('
            LX_ALPHA_SET_SPC(*c, CONST_RECH_LPAREN);
            break;
        case CONST_RECH_RPAREN:
            //')'
            LX_ALPHA_SET_SPC(*c, CONST_RECH_RPAREN);
            break;
        case CONST_RECH_LBRAK:
            //'('
            LX_ALPHA_SET_SPC(*c, CONST_RECH_LBRAK);
            break;
        case CONST_RECH_RBRAK:
            //')'
            LX_ALPHA_SET_SPC(*c, CONST_RECH_RBRAK);
            break;
        case CONST_RECH_STAR:
            //'*'
            LX_ALPHA_SET_SPC(*c, CONST_RECH_STAR);
            break;
        case CONST_RECH_PLUS:
            //'+'
            LX_ALPHA_SET_SPC(*c, CONST_RECH_PLUS);
            break;
        case CONST_RECH_QUES:
            //'?'
            LX_ALPHA_SET_SPC(*c, CONST_RECH_QUES);
            break;
        case CONST_RECH_AMP:
            //'&'
            LX_ALPHA_SET_SPC(*c, CONST_RECH_AMP);
            break;
        case 'n':
            //newline
            LX_ALPHA_SET_SPC(*c, CONST_RECH_NEWLINE);
            break;
        case CONST_RECH_EQ:
            //'='
            LX_ALPHA_SET_SPC(*c, CONST_RECH_EQ);
            break;
        case CONST_RECH_POUND:
            //'='
            LX_ALPHA_SET_SPC(*c, CONST_RECH_POUND);
            break;
        case CONST_RECH_CARROT:
            //'='
            LX_ALPHA_SET_SPC(*c, CONST_RECH_CARROT);
            break;
        default:
            AN(0, "Unknown escaped symbol");
    }
}

/// lex_parseEscapedSymbol
inline void lex_parseSetEscapedSymbol(lparserState* state, lparserInfo* pi, LXAlphaType* c) {
    lconsume(state, c);
    switch(LX_GET_FIXED_VALUE(*c)) {
        case CONST_RECH_BSLASH:
            //a real backslash
            break;
        case '0':
            //null char
            LX_ALPHA_SET_SPC(*c, CONST_RECH_NULLCHR);
            break;
        case 'n':
            //newline
            LX_ALPHA_SET_SPC(*c, CONST_RECH_NEWLINE);
            break;
    }
}

/// lex_parseComment
void lex_parseComment(lparserState* state, lparserInfo* pi) {
    int miss=0;
    while(!LX_CMPALPHA_EQ_SPC(*state->w, CONST_RECH_LF) && !LX_CMPALPHA_EQ_SPC(*state->w, CONST_RECH_CR) && !LX_CMPALPHA_EQ_SPC(*state->w, CONST_RECH_NULL)) {
        if(LX_CMPALPHA_EQ_SPC(*state->w, CONST_RECH_BSLASH)) {
            //line continuation
            ++state->w;
            while(LX_CMPALPHA_EQ_SPC(*state->w, CONST_RECH_LF) || LX_CMPALPHA_EQ_SPC(*state->w, CONST_RECH_CR)) {
                ++state->w;
                miss = 1;
            }
            if(!miss) {
                //backslash was not followed by a line break
                --state->w;
                break;
            }
        }
        ++state->w;
    }
}